package im.starchat.chat.view;

import java.lang.reflect.Field;


import android.content.Context;
import android.os.Handler;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.Scroller;

/**
 * 支持自动轮播、无限循环的 ViewPager
 *
 * @author xinzhang
 */
public class CycleViewPager extends MyViewPager {

    private static final Interpolator sInterpolator = new Interpolator() {
        public float getInterpolation(float t) {
            t -= 1.0F;
            return t * t * t * t * t + 1.0F;
        }
    };

    private AbstractCircleAdapter mAdapter;
    private int mCurrentPage = 0;
    private int mDelayTime = 1000;
    private FixedSpeedScroller mFixedScroller;
    private int mLastMotionAction;
    private boolean mEnableCycle = true;

    private Handler mHandler = new Handler();

    private Runnable mNextRunnable = new Runnable() {
        @Override
        public void run() {
            mHandler.removeCallbacks(mNextRunnable);
            if (isCycle()) {
                mFixedScroller.userCustomDuration(true);
                setCurrentItem(getCurrentItem() + 1, true);
                mHandler.postDelayed(mNextRunnable, mDelayTime);
            }
        }
    };

    public void initPage(int page) {
        mHandler.removeCallbacks(mNextRunnable);
        mCurrentPage = page + (mAdapter.getOffset());
        setCurrentItem(mCurrentPage, true);
    }

    public void initPage(int page, boolean smooth) {
        mHandler.removeCallbacks(mNextRunnable);
        mCurrentPage = page + (mAdapter.getOffset());
        setCurrentItem(mCurrentPage, smooth);
    }

    public void setEnableCycle(boolean enableCycle) {
        mEnableCycle = enableCycle;
        if (mEnableCycle) {
            mHandler.removeCallbacks(mNextRunnable);
            mHandler.postDelayed(mNextRunnable, mDelayTime);
        } else {
            mFixedScroller.userCustomDuration(false);
            mHandler.removeCallbacks(mNextRunnable);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mAdapter == null) {
            return;
        }
        mFixedScroller.userCustomDuration(false);
        mHandler.removeCallbacks(mNextRunnable);
        if (isCycle()) {
            mHandler.postDelayed(mNextRunnable, mDelayTime);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mAdapter == null) {
            return;
        }
        mFixedScroller.userCustomDuration(false);
        mHandler.removeCallbacks(mNextRunnable);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (mAdapter == null) {
            return;
        }
        switch (visibility) {
            case View.VISIBLE:
                mFixedScroller.userCustomDuration(false);
                mHandler.removeCallbacks(mNextRunnable);
                if (isCycle()) {
                    mHandler.postDelayed(mNextRunnable, mDelayTime);
                }
                break;
            default:
                mFixedScroller.userCustomDuration(false);
                mHandler.removeCallbacks(mNextRunnable);
                break;
        }
    }


    public CycleViewPager(Context context) {
        super(context);
        try {
            Field mScroller;
            mScroller = MyViewPager.class.getDeclaredField("mScroller");
            mScroller.setAccessible(true);
            mFixedScroller = new FixedSpeedScroller(getContext(),
                    sInterpolator);
            mScroller.set(this, mFixedScroller);
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    }

    public CycleViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        try {
            Field mScroller;
            mScroller = MyViewPager.class.getDeclaredField("mScroller");
            mScroller.setAccessible(true);
            mFixedScroller = new FixedSpeedScroller(getContext(),
                    sInterpolator);
            mScroller.set(this, mFixedScroller);
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    }


    public void setAbstractCircleAdapter(AbstractCircleAdapter adapter) {
        mAdapter = adapter;
        setAdapter(mAdapter);
        mHandler.removeCallbacks(mNextRunnable);
        if (isCycle()) {
            mHandler.postDelayed(mNextRunnable, mDelayTime);
        }
    }

    private boolean isCycle() {
        return mEnableCycle && mAdapter.getCount() > 1;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mAdapter == null) {
            return super.onTouchEvent(ev);
        }
        mHandler.removeCallbacks(mNextRunnable);
        mFixedScroller.userCustomDuration(false);
        boolean result = super.onTouchEvent(ev);
        mLastMotionAction = ev.getAction() & MotionEventCompat.ACTION_MASK;
        checkScroll();
        return result;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mAdapter == null) {
            return;
        }
        checkScroll();
    }


    private void checkScroll() {
        if (mLastMotionAction == MotionEvent.ACTION_CANCEL
                || mLastMotionAction == MotionEvent.ACTION_UP) {
            if (mFixedScroller.isFinished() && isCycle()) {
                mHandler.removeCallbacks(mNextRunnable);
                mFixedScroller.userCustomDuration(false);
                mHandler.postDelayed(mNextRunnable, mDelayTime);
            }
        }
    }

    public int getDelayTime() {
        return mDelayTime;
    }

    public void setDelayTime(int delayTime) {
        this.mDelayTime = delayTime;
    }

    public static class FixedSpeedScroller extends Scroller {
        private int mDuration = 1000;
        private boolean mUserCustomDuration = false; // 是否使用 mDuration
        // 的值来代替原有scroller 的时间值。

        public int getmDuration() {
            return mDuration;
        }

        public void setmDuration(int mDuration) {
            this.mDuration = mDuration;
        }

        public void userCustomDuration(boolean userCustom) {
            this.mUserCustomDuration = userCustom;
        }

        public FixedSpeedScroller(Context context) {
            super(context);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }


        @Override
        public void startScroll(int startX, int startY, int dx, int dy,
                                int duration) {
            if (mUserCustomDuration) {
                super.startScroll(startX, startY, dx, dy, mDuration);
                mUserCustomDuration = false;
            } else {
                super.startScroll(startX, startY, dx, dy, duration);
            }
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            if (mUserCustomDuration) {
                super.startScroll(startX, startY, dx, dy, mDuration);
                mUserCustomDuration = false;
            } else {
                super.startScroll(startX, startY, dx, dy);
            }
        }
    }

    public static abstract class AbstractCircleAdapter extends PagerAdapter {

        public abstract int getOffset();

//		protected Stack<View> mImageList = new  Stack<View>();
//		protected int mRealCount;
//		protected int mOriRealCount;

//		@Override
//		public int getCount() {
//			if (mRealCount <= 1) {
//				return mRealCount;
//			}
//			return Integer.MAX_VALUE;
//		}

//		public int getOriRealCount(){
//			return mOriRealCount;
//		}

//		/**
//		 * @param realCount 如果 realCount 的值是 2，或 3，那么它会被转化为 4或6 之后再次传递进去。
//		 */
//		public void setRealCount(int realCount) {
//			mOriRealCount = realCount;
//			if (realCount <= 0) {
//				realCount = 0;
//			}
//			if (realCount > 1 && realCount < 4) {
//				realCount = realCount * 2;
//			}
//			this.mRealCount = realCount;
//		}
//
//		private int getRealPosition(int position) {
//			if (mRealCount == 0) {
//				return 0;
//			}
//			return position % mRealCount;
//		}
//
//		@Override
//		public Object instantiateItem(ViewGroup container, int position) {
//			int realPosition = getRealPosition(position);
//			View view =  null ;//mImageList[realPosition];
//			if(mImageList.size()>0){
//				view = mImageList.pop();
//			}
//			int oriReal = realPosition % getOriRealCount();
//			if (view == null) {
//				view = createView(container, position, realPosition,oriReal);
//				container.addView(view, new ViewGroup.LayoutParams(
//						ViewGroup.LayoutParams.FILL_PARENT,
//						ViewGroup.LayoutParams.WRAP_CONTENT));
//			} else {
//				container.addView(view, new ViewGroup.LayoutParams(
//						ViewGroup.LayoutParams.FILL_PARENT,
//						ViewGroup.LayoutParams.WRAP_CONTENT));
//			}
//			initItemView(container, position, realPosition,oriReal,view);
////			LogUtil.i(TAG, "instantiateItem:" + view + ";position:" + position);
//			return view;
//		}
//
//		public abstract void initItemView(ViewGroup container, int position,
//				int realPosition,int oriRealPosition,View object);
//		
//		public abstract View createView(ViewGroup container, int position,
//				int realPosition,int oriRealPosition);
//
//		@Override
//		public void destroyItem(ViewGroup container, int position, Object object) {
//			ImageView iv = (ImageView) object;
//			container.removeView(iv);
//			mImageList.push(iv);
////			LogUtil.i(TAG, "destroyItem:" + object + ";position:" + position);
//		}


    }

}
